﻿using System.Collections.Generic;
using System.Net;
using System.Windows;
using AmazonServices;
using DataStore;
using DataStore.Repositories;
using Infrastructure.CurrentData;
using Infrastructure.Events;
using Infrastructure.Managers;
using Infrastructure.ViewModels;
using log4net;
using System;
using Microsoft.Practices.Composite.Events;
using NHibernate.Validator.Engine;
using UI.Dialogs;
using System.Linq;

namespace UI
{
    /// <summary>
    /// Interaction logic for NewBook.xaml
    /// </summary>
    public partial class NewBook : Window
    {
        IEventAggregator _eventAggregator;
        DialogMode _mode;

        /// <summary>
        /// Initializes a new instance of the <see cref="NewBook"/> class.
        /// </summary>
        public NewBook()
        {
            InitializeComponent();

            _eventAggregator = Current.Container.Resolve<IEventAggregator>();

            addCancel.AddButton.Command = addBookControl.BookVM.SaveCommand;
        }

        public NewBook(BookViewModel bookVM) 
            : this()
        {
            addBookControl.BookVM = bookVM;
            addCancel.AddButton.Command = addBookControl.BookVM.SaveCommand;
        }

        public NewBook(BookViewModel catalogItemVM, DialogMode mode)
            : this(catalogItemVM)
        {
            addBookControl.BookVM = catalogItemVM;

            _mode = mode;
            switch (mode)
            {
                case DialogMode.Create:
                    Title = "Add book";
                    addCancel.AddButton.Content = "Add";
                    break;
                case DialogMode.Update:
                    Title = "Edit book";
                    addCancel.AddButton.Content = "Update";
                    break;
                default:
                    break;
            }
            //addCancel.AddButton.Command = addBookControl.BookVM.SaveCommand;
            
        }

        /// <summary>
        /// Handles the Click event of the cancelButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
            Close();
        }

        /// <summary>
        /// Handles the Click event of the addButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void addButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            var validator = Current.Container.Resolve<ValidatorEngine>();
            var isValid = validator.IsValid(addBookControl.BookVM.Book);
            

            if (isValid)
            {
                try
                {
                    addBookControl.BookVM.SaveCommand.Execute(null);
                
                    if (_mode == DialogMode.Create)
                    {
                        DocumentSavedEvent documentSavedEvent = _eventAggregator.GetEvent<DocumentSavedEvent>();
                        documentSavedEvent.Publish(addBookControl.BookVM);
                    }
                    else if (_mode == DialogMode.Update)
                    {
                        DocumentUpdatedEvent documentUpdatedEvent = _eventAggregator.GetEvent<DocumentUpdatedEvent>();
                        documentUpdatedEvent.Publish(addBookControl.BookVM);
                    }

                    DialogResult = true;
                    Close();
                }
                catch (Exception ex)
                {
                    ILog log = Current.Container.Resolve<ILog>();
                    log.Debug("Failed to save new book.", ex);
                    MessageBox.Show("Failed to save this book. Please try again.", "Save book", MessageBoxButton.OK,
                                    MessageBoxImage.Error);

                }
            }
            else
            {
                MessageBox.Show("There are book data fields with improper values. Book cannot be saved.");
            }
        }

        // TODO rewrite to use controller class
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            UpdateSingleBook updateForm = new UpdateSingleBook();

            // Set search data from existing book data
            updateForm.UpdateControl.Title.Text = addBookControl.BookVM.Title;
            updateForm.UpdateControl.ISBN.Text = addBookControl.BookVM.ISBN;
            foreach (var author in addBookControl.BookVM.Authors)
            {
                updateForm.UpdateControl.Author.Text += string.Format("{0} {1} ", author.FirstName, author.LastName);
            }

            updateForm.Owner = this;
            updateForm.ShowInTaskbar = false;
            if (updateForm.ShowDialog() == true)
            {
                AmazonBook selectedBook = updateForm.UpdateControl.Selected;

                addBookControl.BookVM.Title = selectedBook.Title;
                addBookControl.BookVM.ISBN = selectedBook.ISBN;
                addBookControl.BookVM.NumberOfPages = selectedBook.NumberOfPages;

                // Set authors
                if (selectedBook.Authors != null && selectedBook.Authors.Count > 0)
                {
                    if (addBookControl.BookVM.Authors == null)
                    {
                        addBookControl.BookVM.Authors = new List<AuthorViewModel>();
                    }

                    IDatabase database = Current.Container.Resolve<IDatabase>();
                    using (var unitOfWork = database.CreateUnitOfWork())
                    {
                        AuthorRepository repo = new AuthorRepository(unitOfWork);

                        foreach (var author in selectedBook.Authors)
                        {
                            // Check if author exists


                            if (repo.Exists(author))
                            {
                                // Set existing author
                                var existingAuthor = repo.GetAuthors(author).FirstOrDefault();
                                addBookControl.BookVM.Authors.Add(new AuthorViewModel(existingAuthor));
                            }
                            else
                            {
                                // Set a new author
                                addBookControl.BookVM.Authors.Add(new AuthorViewModel(author));
                            }
                        }
                    }
                }

                // Set covers
                if(selectedBook.Cover != null && selectedBook.Cover.Count > 0)
                {

                    if(addBookControl.BookVM.Cover == null)
                    {
                        addBookControl.BookVM.Cover = new List<CoverViewModel>();
                    }
                    foreach (var cover in selectedBook.Cover)
                    {
                        CoverManager manager = new CoverManager();
                        var newFilePath = manager.Download(cover.Path.Uri);
                        cover.Path.Uri = new Uri(newFilePath);

                        addBookControl.BookVM.Cover.Add(new CoverViewModel(cover));
                    }
                }
            }

        }

       
    }
}
